Skip to content

feat(ui): visible auth-required affordance on 401#76

Merged
aksOps merged 2 commits intomainfrom
feat/ui-auth-affordance
Apr 24, 2026
Merged

feat(ui): visible auth-required affordance on 401#76
aksOps merged 2 commits intomainfrom
feat/ui-auth-affordance

Conversation

@aksOps
Copy link
Copy Markdown
Contributor

@aksOps aksOps commented Apr 24, 2026

Summary

  • New AuthRequiredBanner renders a visible "Sign in required" state-card inside <main> whenever any React Query throws ApiErrorResponse { status: 401 }.
  • Wired via a global QueryCache onError that flips a tiny useAuthStore (zustand) — individual query consumers stay unchanged.
  • Removes test.fixme from ui/e2e/auth.spec.ts; both smokes (/ and /notes) now pass and assert both the testid and the auth-copy regex.

Closes #66.

Test Plan

  • Vitest: 2 new banner tests + 2 store tests; full UI suite 85/85 green
  • TypeScript typecheck clean
  • Playwright e2e auth smokes re-enabled, assertions match copy

Previously a 401 from /api/* bubbled into React Query error states
without a recognisable "sign in" surface, so the user saw a generic
"Could not load activity" card with no hint that the problem was
authentication. The auth.spec.ts Playwright smokes were held back
with test.fixme for this reason.

Wiring:
- `useAuthStore` (zustand) holds a single `authRequired` flag.
- QueryCache `onError` flips the flag when any React Query throws an
  ApiErrorResponse with status === 401 — a global gate so individual
  query callers don't each have to handle 401.
- AuthRequiredBanner reads the flag and renders a `role="alert"`
  state-card with copy matching the flake-register regex ("Sign in",
  "session has expired", "please sign in").
- Mounted inside <main id="main"> in Shell.tsx so it appears on every
  route without per-route plumbing.

Re-enables ui/e2e/auth.spec.ts (two smokes, /`/` and `/notes`) and
asserts both the testid and the auth-copy regex. Vitest coverage for
the store + banner added.

Closes #66.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aksOps aksOps enabled auto-merge (squash) April 24, 2026 04:39
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: af53672508

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ui/src/components/layout/Providers.tsx Outdated
Codex flagged the original auth gate as incomplete: the onError was
only attached to QueryCache, so a 401 thrown by a mutation (note
create/update/delete) would slip past and leave the user staring at
an unhelpful transient error with no "Sign in required" affordance.

Extract the 401 detector into a shared `gateUnauthorized(error)`
helper and attach it to BOTH QueryCache and MutationCache. Add three
Vitest cases: query-401 flips, mutation-401 flips, and a non-401
error does NOT flip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aksOps aksOps merged commit dd61b92 into main Apr 24, 2026
12 checks passed
@aksOps aksOps deleted the feat/ui-auth-affordance branch April 24, 2026 04:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

flake-register: add unauthed UI affordance + re-enable auth.spec.ts

1 participant